/*
 * Copyright 2015-2016 Tumblr, Inc.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tumblr.backboard.example;

import com.facebook.rebound.Spring;
import com.facebook.rebound.SpringSystem;
import com.tumblr.backboard.Actor;
import com.tumblr.backboard.MotionProperty;
import com.tumblr.backboard.Utils.View;
import com.tumblr.backboard.imitator.EventImitator;
import com.tumblr.backboard.imitator.MotionImitator;
import com.tumblr.backboard.performer.Performer;
import ohos.agp.components.Component;
import ohos.agp.utils.Rect;

import java.security.SecureRandom;

/**
 * A dialog-like animation.
 *
 * @author ericleong
 * @since 2021-05-07
 */
public class AppearFragment extends BaseFraction {
    private Component[] mCircles;
    private Component mLayoutComponent;
    private SpringSystem mSpringSystem = SpringSystem.create();

    private Spring[] mSprings = new Spring[VALUE_SIX];
    private Actor[] mActors = new Actor[VALUE_SIX];

    @Override
    public int getUiContent() {
        return ResourceTable.Layout_fragment_appear;
    }

    @Override
    public void initComponent() {
        mLayoutComponent = mComponent.findComponentById(ResourceTable.Id_layout);

        // grab the circles
        mCircles = new Component[VALUE_SIX];
        mCircles[VALUE_ZERO] = mComponent.findComponentById(ResourceTable.Id_circle0);
        mCircles[VALUE_ONE] = mComponent.findComponentById(ResourceTable.Id_circle1);
        mCircles[VALUE_TWO] = mComponent.findComponentById(ResourceTable.Id_circle2);
        mCircles[VALUE_THREE] = mComponent.findComponentById(ResourceTable.Id_circle3);
        mCircles[VALUE_FOUR] = mComponent.findComponentById(ResourceTable.Id_circle4);
        mCircles[VALUE_FIVE] = mComponent.findComponentById(ResourceTable.Id_circle5);

        initComponentClickedListener();

        mLayoutComponent.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                // grab location of root view so we can compensate for it
                int[] rootLocation = new int[VALUE_TWO];
                Rect rect = component.getComponentPosition();
                rootLocation[0] = rect.left;
                rootLocation[1] = rect.top;
                for (int index = 0; index < mCircles.length; index++) {
                    if (mSprings[index].getEndValue() == 0) { // hide
                        int[] location = mCircles[index].getLocationOnScreen();

                        // if the end values are different, they will move at different speeds
                        mSprings[index].setEndValue(mLayoutComponent.getHeight() - location[1] + rootLocation[1]
                                + VALUE_TWO * (new SecureRandom().nextDouble()) * mCircles[index].getHeight());
                    } else {
                        mActors[index].setTouchEnabled(true);

                        for (Actor.Motion motion : mActors[index].getMotions()) {
                            for (EventImitator imitator : motion.getImitators()) {
                                if (imitator instanceof MotionImitator) {
                                    imitator.getSpring().setCurrentValue(0);
                                }
                            }
                        }
                        mSprings[index].setEndValue(0); // appear
                    }
                }
            }
        });
    }

    private void initComponentClickedListener() {
        // the selected view should move to heaven and the unselected ones should go to hell
        Component.ClickedListener select = new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Spring spring = (Spring) component.getTag();

                // get root location so we can compensate for it
                int[] rootLocation = mLayoutComponent.getLocationOnScreen();
                for (int index = 0; index < mCircles.length; index++) {
                    mActors[index].setTouchEnabled(false);

                    for (Actor.Motion motion : mActors[index].getMotions()) {
                        for (EventImitator imitator : motion.getImitators()) {
                            if (imitator instanceof MotionImitator) {
                                final MotionImitator motionImitator = (MotionImitator) imitator;
                                if (motionImitator.getProperty() != MotionProperty.Y) {
                                    imitator.release(null);
                                }
                            }
                        }
                    }
                    int[] location = mCircles[index].getLocationOnScreen();

                    if (mSprings[index] == spring) {
                        // goes to the top
                        mSprings[index].setEndValue(-location[1] + rootLocation[1] - component.getHeight());
                    } else {
                        // go back to the bottom
                        mSprings[index].setEndValue(mLayoutComponent.getHeight() - location[1] + rootLocation[1]
                                + VALUE_TWO * (new SecureRandom().nextDouble()) * mCircles[index].getHeight());
                    }
                }
            }
        };

        // attach listeners
        for (int index = 0; index < mCircles.length; index++) {
            mSprings[index] = mSpringSystem.createSpring();
            mSprings[index].addListener(new Performer(mCircles[index], View.TRANSLATION_Y));
            mCircles[index].setTag(mSprings[index]);
            mCircles[index].setClickedListener(select);
            mActors[index] =
                    new Actor.Builder(mSpringSystem, mCircles[index]).addTranslateMotion(MotionProperty.X)
                            .addTranslateMotion(MotionProperty.Y).build();
        }
    }
}